#include "replication_ignore.h"
#include "locking.h"
#include "log.h"
#include <map>
#include <assert.h>
#define USESUM
using namespace std;
typedef long long int LL;
typedef unsigned long long int ULL;
static LOCK truncateCountMapLock;
static LOCK insertSizeMapLock;
static LOCK deleteSizeMapLock;
static map<string, ULL> deleteSizeMap;
#ifdef USESUM
static map<string, ULL> insertSizeMap;
#endif
static map<string, unsigned int> truncateCountMap;
typedef struct Node_st {
	Node_st() {
		val = -1;
		next = NULL;
	}
	size_t val;
	struct Node_st *next;
} Node;
namespace repl_ignore {

static FILE* logp;
#ifndef USESUM

Node* first_insert = NULL, *last_insert = first_insert;
Node *first_delete = NULL, *last_delete = first_delete;

static void repl_log(string s) {
	//FILE* f = fopen(logfile, "a");
	fprintf(logp, "%s\n", s.c_str());
	//fflush(logp);
}
#endif

void init() {
	logp = fopen("/tmp/sqlfslog/replicationlog", "w");
}

void inc_truncate(const string& table) {
	SRLock lock(truncateCountMapLock);
	int count = truncateCountMap[table];
	truncateCountMap[table] = count + 1;
}
bool shall_skip_truncate(const string& table) {
	SRLock lock(truncateCountMapLock);
	int count = truncateCountMap[table];

	if(count > 0) {

		truncateCountMap[table] = count - 1;
		return true;
	}
	return false;

}
void add_insert(const string& table, size_t rowSize) {
	SRLock lock(insertSizeMapLock);
#ifdef USESUM
	int size = insertSizeMap[table];
	insertSizeMap[table] =  size + rowSize;
#else
	char buf[100];
	sprintf(buf, "insert of size %lu", rowSize);
	repl_log(buf);
	Node *node = new Node();
	node->next = NULL;
	node->val = rowSize;
	if(first_insert == NULL)
		first_insert = last_insert = node;
	else {
		last_insert->next = node;
		last_insert = node;
	}
#endif
}
void add_delete(const string& table, size_t rowSize) {
	SRLock lock(insertSizeMapLock);
	int size = deleteSizeMap[table];
	deleteSizeMap[table] = size + rowSize;
}
bool shall_skip_insert(const string& table, size_t rowSize) {
	SRLock lock(insertSizeMapLock);
#ifdef USESUM
	ULL size = insertSizeMap[table];
	if(size > 0) {
		assert(size >= rowSize);
		insertSizeMap[table] = size - rowSize;
		return true;
	}
#else
	char buf[100];
	sprintf(buf, "skip insert of size %lu", rowSize);
	repl_log(buf);
	if(first_insert != NULL) {
		assert(first_insert->val == rowSize);
		Node* tmp = first_insert;
		first_insert = first_insert->next;
		delete tmp;
		return true;
	}

#endif
	return false;
}
bool shall_skip_delete(const string& table, size_t rowSize) {
	SRLock lock(deleteSizeMapLock);
	ULL size = deleteSizeMap[table];
	if(size > 0) {
		assert(size >= rowSize);
		return true;
	}
	return false;
}
}
